﻿using System;
using System.Collections.Generic;

using RexToy.DesignPattern;
using RexToy.Collections;
using RexToy.Cassandra.Meta;

namespace RexToy.Cassandra
{
    class CassandraContext : DisposableBase, ICassandraContext
    {
        internal CassandraContext(Cluster cluster, string keyspace)
        {
            _read = ConsistencyLevel.Quorum;
            _write = ConsistencyLevel.Quorum;
            Init(cluster, keyspace);
        }

        internal CassandraContext(Cluster cluster, string keyspace, ConsistencyLevel level)
        {
            if (_read == ConsistencyLevel.Any)
                throw ExceptionHelper.CreateReadConsistencyAny();

            _read = level;
            _write = level;
            Init(cluster, keyspace);
        }

        internal CassandraContext(Cluster cluster, string keyspace, ConsistencyLevel read, ConsistencyLevel write)
        {
            if (_read == ConsistencyLevel.Any)
                throw ExceptionHelper.CreateReadConsistencyAny();

            _read = read;
            _write = write;
            Init(cluster, keyspace);
        }

        private Connection _cnn;
        private string _ks;
        private ConsistencyLevel _read;
        private ConsistencyLevel _write;
        private void Init(Cluster cluster, string keyspace)
        {
            _ks = keyspace;
            _cnn = new Connection(cluster, keyspace);
            _cnn.Open();
        }

        public string ClusterName
        {
            get { return _cnn.Client.describe_cluster_name(); }
        }

        public string APIVersion
        {
            get { return _cnn.Client.describe_version(); }
        }

        public SchemaVersion SchemaVersion
        {
            get { return new SchemaVersion(_cnn.Client.describe_schema_versions()); }
        }

        protected override void DisposeManagedObject()
        {
            _cnn.Dispose();
        }

        public IColumnFamily<K, C> GetColumnFamily<K, C>(string name)
        {
            var cfInfo = MetaCache.Instance().GetMeta(_ks, name, _cnn);
            var cf = new ColumnFamily<K, C>(_ks, name, cfInfo, _cnn.Client, _read, _write);
            return cf;
        }

        public ICounterColumnFamily<K, C> GetCounterColumnFamily<K, C>(string name)
        {
            var cfInfo = MetaCache.Instance().GetMeta(_ks, name, _cnn);
            var cf = new CounterColumnFamily<K, C>(_ks, name, cfInfo, _cnn.Client, ConsistencyLevel.One, ConsistencyLevel.One);//Refactor: consist level
            return cf;
        }

        public ISuperColumnFamily<K, C, SUB> GetColumnFamily<K, C, SUB>(string name)
        {
            var cfInfo = MetaCache.Instance().GetMeta(_ks, name, _cnn);
            var cf = new SuperColumnFamily<K, C, SUB>(_ks, name, cfInfo, _cnn.Client, _read, _write);
            return cf;
        }
    }
}
